package org.aerie.forest.extensions.datatransmit.brick.exportdata;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.aerie.forest.core.brick.exception.custom.runtime.ForestRuntimeException;
//import org.aerie.forest.extensions.datatransmit.brick.analytictype.TransmittableBasicDataType;
import org.aerie.forest.extensions.datatransmit.brick.analytictype.multiton.MultitonTransmittableClass;
import org.aerie.forest.extensions.datatransmit.brick.annotation.TransmitPrimaryKey;
//import org.aerie.forest.extensions.datatransmit.brick.analytictype.SingleTransmittableClass;
import org.aerie.forest.extensions.datatransmit.brick.exception.ForestModifierException;

/**
 * @description 导出数据块
 *
 * @author quark
 * @organization aerie
 * @date 2020年3月6日 下午2:13:36
 * @version 1.2.0
 */
public abstract class DerivedDataLump {

	/**
	 * Construction
	 * 
	 *
	 * @date 2020年3月7日 下午4:22:57
	 */
	protected DerivedDataLump() {
		super();
		int modifiers = this.getClass().getModifiers();
		if (!Modifier.isFinal(modifiers) || !Modifier.isPublic(modifiers)) {
			throw new ForestRuntimeException("类的修饰符必须是public+final") {

				/**
				 * @description 序列化编号
				 * 
				 * @author quark
				 * @date 2020年3月7日 下午4:41:17
				 */
				private static final long serialVersionUID = 1L;
			};
		}
	}

	/**
	 * @description 校验类的设计是否合法
	 * @throws Exception “不合法”的异常
	 *
	 * @date 2020年3月7日 下午4:24:57
	 */
	public void isLegal() throws Exception {
		// 校验
		fieldsLegal(this.getClass());

	}

	/**
	 * @description 数据块的字段校验
	 * @param zclass 需要校验的数据块的类
	 * @throws Exception 校验失败的异常
	 *
	 * @date 2020年3月9日 上午11:22:14
	 */
	private void fieldsLegal(Class<?> zclass) throws Exception {
		Field[] fields = zclass.getDeclaredFields();
		// 主键注解的数量
		int transmitPrimaryKeyNum = 0;
		for (int num = 0; num < fields.length; num++) {
			// 字段
			Field field = fields[num];
			// 可传输主键标识
			int transmitPrimaryKey = isTransmitPrimaryKey(field);
			transmitPrimaryKeyNum += transmitPrimaryKey;
			// 校验数据块的
			int modifiers = field.getModifiers();
			if (!Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) {
				throw new ForestModifierException("导入数据块的属性必须是private，不能是static");
			}
			String typeName = field.getGenericType().getTypeName();
			// 如果是集合
			if (!field.getType().isPrimitive() && multitonTransmittable(typeName)) {
				// 校验主键注解
				if (transmitPrimaryKey == 1)
					throw new ForestModifierException("可传输集合不能做可传输主键");
				ParameterizedType listGenericType = (ParameterizedType) field.getGenericType();
				Type[] listActualTypeArguments = listGenericType.getActualTypeArguments();
				Type type = listActualTypeArguments[0];
				System.err.println(type);
			} else {
				// TODO
			}
//			Class<?> zclassField = null;
//			if (Class.forName(typeName).isAssignableFrom(DerivedDataLump.class)) {
//				if (transmitPrimaryKey == 1)
//					throw new TransmitPrimaryKeyException(DerivedDataLump.class.getName() + "不可以作为可传输主键");
//				// 递归校验
//				fieldsLegal(zclassField);
//			} else {
//				// 分情况讨论【是否是多例可传输类型】
//				if (!MultitonTransmittable(typeName)) {
//					// 校验单例类型是否可传输
//					singleTransmittable(typeName);
//				}
//			}
		}
		System.out.println(transmitPrimaryKeyNum);
		if (transmitPrimaryKeyNum != 1)
			throw new ForestModifierException("可传输数据块中有且只能有一个可传输主键");
	}

	/**
	 * @description 单例可传输校验[内部方法不校验类型名称是否为空]
	 * @param typeName 类型名称
	 * @throws Exception 校验不成功的异常
	 *
	 * @date 2020年3月10日 上午9:48:13
	 */
//	private void singleTransmittable(String typeName) throws Exception {
//		// 校验是否是可传输包装类
//		for (SingleTransmittableClass transmittableClass : SingleTransmittableClass.values()) {
//			if (transmittableClass.getTypeName().equals(typeName))
//				return;
//		}
//		for (TransmittableBasicDataType transmittableBasicDataType : TransmittableBasicDataType.values()) {
//			if (transmittableBasicDataType.getTypeName().equals(typeName))
//				return;
//		}
//	}

	/**
	 * @description 集合可传输校验[内部方法不校验类型名称是否为空]
	 * @param typeName 类型名称
	 * @return 判断结果
	 * @throws ClassNotFoundException
	 *
	 * @date 2020年3月10日 上午10:00:12
	 */
	private boolean multitonTransmittable(String typeName) throws Exception {
		int index = typeName.indexOf('<');
		if (index != -1) {
			typeName = typeName.substring(0, index);
		}
		for (MultitonTransmittableClass multitonTransmittableClass : MultitonTransmittableClass.values()) {
			if (multitonTransmittableClass.getZclass().isAssignableFrom(Class.forName(typeName))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @description 校验字段时候为可传输主键【内部方法不判空】
	 * @param field 需要校验的字段
	 * @return 0:没有主键注解；1：有主键注解
	 *
	 * @date 2020年3月10日 下午12:50:25
	 */
	private int isTransmitPrimaryKey(Field field) {
		Annotation[] annotations = field.getAnnotations();
		int length = 0;
		// 无注解返回0
		if ((length = annotations.length) == 0)
			return 0;
		for (int num = 0; num < length; num++) {
			// 找到主键注解返回1
			if (annotations[num].annotationType().hashCode() == TransmitPrimaryKey.class.hashCode())
				return 1;
		}
		// 没有找到返回0
		return 0;
	}
}
